package com.kancy.kie.server.client.config;

import com.kancy.kie.server.client.cryptor.PasswordCryptor;
import com.kancy.kie.server.client.cryptor.SimplePasswordCryptor;
import com.kancy.kie.server.client.properties.DroolsKieServerProperties;
import com.kancy.kie.server.client.service.DroolsRuleEngine;
import com.kancy.kie.server.client.service.SimpleDroolsRuleEngine;
import org.kie.server.api.marshalling.MarshallingFormat;
import org.kie.server.client.KieServicesClient;
import org.kie.server.client.KieServicesConfiguration;
import org.kie.server.client.KieServicesFactory;
import org.kie.server.client.RuleServicesClient;
import org.kie.server.client.balancer.BalancerStrategy;
import org.kie.server.client.balancer.LoadBalancer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * DroolsKieServerClientAutoConfiguration
 * <p>
 *
 * @author: kancy
 * @date: 2020/3/12 12:54
 **/
@EnableConfigurationProperties
public class DroolsKieServerClientAutoConfiguration {
    /**
     * kie server url path
     */
    private static final String KIE_SERVER_URL_PATH = "/kie-server/services/rest/server";

    @Bean
    @ConfigurationProperties(prefix = "drools.kie.server")
    public DroolsKieServerProperties droolsKieServerProperties(){
        return new DroolsKieServerProperties();
    }

    /**
     * kie server 负载轮询均衡器
     * @param droolsKieServerProperties
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    public LoadBalancer loadBalancer(DroolsKieServerProperties droolsKieServerProperties){
        List<String> urls = new ArrayList<>();
        Arrays.stream(droolsKieServerProperties.getNodes())
                .forEach(node -> urls.add(String.format("http://%s%s",node, KIE_SERVER_URL_PATH)));
        return LoadBalancer.forStrategy(urls, BalancerStrategy.Type.ROUND_ROBIN_STRATEGY);
    }

    /**
     * KieServicesConfiguration
     * @param droolsKieServerProperties
     * @param loadBalancer
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    public KieServicesConfiguration kieServicesConfiguration(DroolsKieServerProperties droolsKieServerProperties,
                                                             LoadBalancer loadBalancer){
        PasswordCryptor passwordCryptor = new SimplePasswordCryptor();
        KieServicesConfiguration config = KieServicesFactory.newRestConfiguration(loadBalancer.getUrl(),
                passwordCryptor.decrypt(droolsKieServerProperties.getUsername()), passwordCryptor.decrypt(droolsKieServerProperties.getPassword()));
        config.setMarshallingFormat(MarshallingFormat.JSON);
        config.setTimeout(droolsKieServerProperties.getTimeout().toMillis());
        config.setHeaders(droolsKieServerProperties.getHeaders());
        config.setLoadBalancer(loadBalancer);
        config.setExtraClasses(droolsKieServerProperties.getExtraClasses());
        return config;
    }

    /**
     * KieServicesClient
     * @param kieServicesConfiguration
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    public KieServicesClient kieServicesClient(KieServicesConfiguration kieServicesConfiguration){
        return KieServicesFactory.newKieServicesClient(kieServicesConfiguration);
    }

    /**
     * RuleServicesClient
     * @param kieServicesClient
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    public RuleServicesClient ruleServicesClient(KieServicesClient kieServicesClient){
        return kieServicesClient.getServicesClient(RuleServicesClient.class);
    }

    /**
     * DroolsRuleEngine
     * @param ruleServicesClient
     * @param droolsKieServerProperties
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    public DroolsRuleEngine droolsRuleEngine(RuleServicesClient ruleServicesClient,
                                             DroolsKieServerProperties droolsKieServerProperties){
        return new SimpleDroolsRuleEngine(ruleServicesClient, droolsKieServerProperties);
    }
}
